﻿/**********************************************************************************
 * 作者：Darren Zhou
 * 小组：开发小组
 * 说明： SQLServerHelper数据库助手类
 *创建日期：2018-09-04 00:23:04
 * 版本号：V1.0.0
* *********************************************************************************/
using Common.DataBase.Interface;
using Common.Utils;
using CommonUtils.Attributes;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Reflection;

namespace Common.DataBase.Implement {
  public class SQLServerHelper : ISQLHelper {

    private static log4net.ILog _logger = log4net.LogManager.GetLogger(typeof(SQLServerHelper));

    private string connectString = null;
    private string queryUserTableSQL = null;
    private string queryColumnsByTableNameSQL = null;
    private Dictionary<string, string> dataTypeMap = new Dictionary<string, string>();
    private SqlConnection  connection= null;

    /// <summary>
    /// 数据库连接字符串
    /// </summary>
    public string ConnectString {
      get {
        return connectString;
      }
    }

    /// <summary>
    /// 数据库类型
    /// </summary>
    public DataBaseType DBType {
      get {
        return DataBaseType.SQLServer;
      }
    }

    /// <summary>
    /// 查询所有用户表的字符串
    /// </summary>
    public string QueryUserTableSQL {
      get {
        return queryUserTableSQL;
      }
    }

    /// <summary>
    /// 根据指定表名查询列信息的SQL
    /// </summary>
    public string QueryColumnsByTableNameSQL {
      get {
        return queryColumnsByTableNameSQL;
      }
    }
    /// <summary>
    /// 数据类型映射关系
    /// </summary>
    public Dictionary<string, string> DataTypeMap {
      get {
        return dataTypeMap;
      }
    }


    public SQLServerHelper() {
      connectString = ConfigurationManager.AppSettings["appDataBase"];
      if(string.IsNullOrWhiteSpace(connectString)) {
        connectString = ConfigurationManager.ConnectionStrings["appDataBase"].ConnectionString;
      }
      connection = new SqlConnection(connectString );
    }

    /// <summary>
    /// 构造SQL参数
    /// </summary>
    /// <param name="parameterName">参数名</param>
    /// <param name="value">参数值</param>
    /// <returns>参数对象</returns>
    public DbParameter DbParam(string parameterName, object value) {
      return new SqlParameter(parameterName, value);
    }

    #region "打开数据库连接"
    /// <summary>
    /// 打开数据库连接
    /// </summary>
    /// <returns></returns>
    public DbConnection OpenConnection() {
      if(connection != null && connection.State != ConnectionState.Open) {
        connection.Open();
      }
      return connection;
    }
    #endregion


    #region "关闭数据库连接"
    /// <summary>
    /// 打开数据库连接
    /// </summary>
    /// <returns></returns>
    public void CloseConnection() {
      if(connection != null && connection.State != ConnectionState.Open) {
        connection.Close();
      }
    }
    #endregion


    /// <summary>
    /// 执行不带参数的增删改SQL语句
    /// </summary>
    /// <param name="commandText">要执行的SQL语句或存储 过程</param>
    /// <returns>返回受影响的记录数</returns>
    public int ExecuteNonQuery(string commandText, bool isClose = true) {
      return ExecuteNonQuery(commandText, CommandType.Text,  isClose);
    }


    /// <summary>
    /// 执行不带参数的增删改SQL语句或存储过程
    /// </summary>
    /// <param name="commandText">要执行的SQL语句</param>
    /// <param name="commandType">命令类型</param>
    /// <param name="isClose">执行完是否关闭连接</param>
    /// <returns>返回受影响的记录数</returns>
    public int ExecuteNonQuery( string commandText, CommandType commandType = CommandType.Text,bool isClose = true) {
      return ExecuteNonQuery( commandText, commandType, null, isClose);
    }





    /// <summary>
    /// 执行带参数的增删改SQL语句或存储过程
    /// </summary>
    /// <param name="commandText">要执行的SQL语句</param>
    /// <param name="commandType">命令类型</param>
    /// <param name="parameters">参数集合</param>
    /// <param name="isClose">执行完是否关闭连接</param>
    /// <returns>返回受影响的记录数</returns>
    public int ExecuteNonQuery( string commandText, CommandType commandType, DbParameter[] parameters = null, bool isClose = true) {
      int effectiveRowCount = 0;
      try {
        OpenConnection();
        SqlCommand command = new SqlCommand( commandText, connection );
        command.CommandType = commandType;
        if(parameters != null && parameters.Length > 0) {
          command.Parameters.AddRange(parameters);
        }
        effectiveRowCount = command.ExecuteNonQuery();
      } catch(Exception exception) {
        foreach(DbParameter parmeter in parameters) {
          commandText = commandText.Replace(parmeter.ParameterName, string.Format("'{0}'", parmeter.Value));
        }
        _logger.Debug(commandText);
        _logger.Error( exception );
      } finally {
        if (isClose == true) {
          CloseConnection();
        }        
      }
      return effectiveRowCount;
    }


    /// <summary>
    /// 执行不带参数的SQL查询语句
    /// </summary>
    /// <param name="commandText">SQL查询语句或存储过程</param>
    /// <param name="isClose">执行完是否关闭连接</param>
    /// <returns></returns>
    public DataTable ExecuteQuery(string commandText, bool isClose = true) {
      return ExecuteQuery(commandText, CommandType.Text, isClose);
    }

    /// <summary>
    /// 执行不带参数的SQL查询语句
    /// </summary>
    /// <param name="commandText">要执行的SQL语句</param>
    /// <param name="commandType">命令类型</param>
    /// <param name="isClose">执行完是否关闭连接</param>
    /// <returns></returns>
    public DataTable ExecuteQuery( string commandText, CommandType commandType, bool isClose = true) {
      return ExecuteQuery( commandText, commandType, null , isClose);
    }


    /// <summary>
    /// 执行带参数的SQL查询语句
    /// </summary>
    /// <param name="commandText">要执行的SQL语句</param>
    /// <param name="commandType">命令类型</param>
    /// <param name="parameters">参数集合</param>
    /// <param name="isClose">执行完是否关闭连接</param>
    /// <returns></returns>
    public DataTable ExecuteQuery( string commandText, CommandType commandType, DbParameter[] parameters, bool isClose = true) {
      DataTable dataTable = new DataTable();
      try {
        OpenConnection();
        SqlCommand command = new SqlCommand( commandText, connection );
        command.CommandType = commandType;
        if(parameters != null && parameters.Length > 0) {
          command.Parameters.AddRange(parameters);
        }
        using(DbDataAdapter dataAdapter = new SqlDataAdapter(command)) {
          DataSet dataSet = new DataSet();
          dataAdapter.FillSchema( dataSet, SchemaType.Source );
          dataAdapter.Fill( dataSet );    //加载表数据
          dataTable = dataSet.Tables[0];
        }
      } catch(Exception exception) {
        foreach(DbParameter parmeter in parameters) {
          commandText = commandText.Replace(parmeter.ParameterName, string.Format("'{0}'", parmeter.Value));
        }
        _logger.Debug(commandText);
        _logger.Error( exception );
        dataTable = null;
      } finally {
        if (isClose == true) {
          CloseConnection();
        }
      }
      return dataTable;
    }

    /// <summary>
    /// 查询对象集合
    /// 执行传入的不带参数的SQL查询语句或存储过程
    /// </summary>
    /// <typeparam name="T">返回的集合中的数据类型</typeparam>
    /// <param name="commandText">SQL查询语句或存储过程</param>
    /// <param name="isClose">执行完是否关闭连接</param>
    /// <returns></returns>
    public List<T> FindList<T>(string commandText, bool isClose = true) where T : new() {
      return FindList<T>(commandText, CommandType.Text, isClose);
    }


    /// <summary>
    /// 查询对象集合
    /// 执行传入的不带参数的SQL查询语句或存储过程
    /// </summary>
    /// <typeparam name="T">返回的集合中的数据类型</typeparam>
    /// <param name="commandText">要执行的SQL语句</param>
    /// <param name="commandType">命令类型</param>
    /// <param name="parameters">参数集合</param>
    /// <param name="isClose">执行完是否关闭连接</param>
    /// <returns></returns>
    public List<T> FindList<T>(string commandText, CommandType commandType, bool isClose = true) where T : new() {
      return FindList<T>(commandText, CommandType.Text, null, isClose);
    }


    /// <summary>
    /// 查询对象集合
    /// 该方法执行带参数的SQL查询语句
    /// </summary>
    /// <typeparam name="T">返回的集合中的数据类型</typeparam>
    /// <param name="commandText">要执行的SQL语句</param>
    /// <param name="commandType">命令类型</param>
    /// <param name="parameters">参数集合</param>
    /// <param name="isClose">执行完是否关闭连接</param>
    /// <returns></returns>
    public List<T> FindList<T>(string commandText, CommandType commandType, DbParameter[] parameters, bool isClose = true) where T : new() {
      DataTable dataTable = ExecuteQuery(commandText, commandType, parameters, isClose);
      PropertyInfo[] properties = typeof(T).GetProperties();
      List<T> entitys = new List<T>();//创建实体
      if (dataTable.Rows.Count > 0) {
        foreach (DataRow dataRow in dataTable.Rows) {
          T entity = new T();
          foreach (PropertyInfo property in properties) {
            Attribute[] dbColumnAttributes = Attribute.GetCustomAttributes(property);
            foreach (Attribute dbColumnAttr in dbColumnAttributes) {
              if (dbColumnAttr.GetType() == typeof(DBColumn)) {
                string fieldName = ((DBColumn)dbColumnAttr).ColumnName;
                object value = dataRow[fieldName];
                if (value != DBNull.Value && property.CanWrite) {
                  if (property.PropertyType.Name.EndsWith("DateTime")) {
                    property.SetValue(entity, Convert.ToDateTime(value), null);
                  } else {
                    property.SetValue(entity, value, null);
                  }
                }
                break;
              }
            }
          }
          entitys.Add(entity);
        }
      }
      return entitys;
    }

    /// <summary>
    /// 从数据库中检索单个值
    /// </summary>
    /// <param name="commandText">SQL查询语句或存储过程</param>
    /// <param name="isClose">执行完是否关闭连接</param>
    /// <returns>返回值是object类型</returns>
    public object ExecuteScalar(string commandText, bool isClose = true) {
      return ExecuteScalar(commandText, null, isClose);
    }

    /// <summary>
    /// 从数据库中检索单个值
    /// </summary>
    /// <param name="commandText">SQL查询语句或存储过程</param>
    /// <param name ="commandType">命令类型</param>
    /// <param name="isClose">执行完是否关闭连接</param>
    /// <returns>返回值是object类型</returns>
    public object ExecuteScalar(string commandText, DbParameter[] parameters, bool isClose = true) {
      return ExecuteScalar(commandText, parameters, CommandType.Text, isClose);
    }

    /// <summary>
    /// 从数据库中检索单个值
    /// </summary>
    /// <param name="commandText">要执行的SQL语句</param>
    /// <param name ="commandType">命令类型</param>
    /// <param name="parameters">参数集合</param>
    /// <param name="isClose">执行完是否关闭连接</param>
    /// <returns>返回值是object类型</returns>
    public object ExecuteScalar(string commandText, DbParameter[] parameters, CommandType commandType, bool isClose = true) {
      object result = null;
      try {
        OpenConnection();
        SqlCommand command = new SqlCommand(commandText, connection);
        command.CommandType = commandType;
        if(parameters != null && parameters.Length > 0) {
          command.Parameters.AddRange(parameters);
        }
        result = command.ExecuteScalar();
      } catch(Exception exception) {
        foreach(DbParameter parmeter in parameters) {
          commandText = commandText.Replace(parmeter.ParameterName, string.Format("'{0}'", parmeter.Value));
        }
        _logger.Debug(commandText);
        _logger.Error(exception);
      } finally {
        if(isClose == true) {
          CloseConnection();
        }
      }
      return result;
    }


    /// <summary>
    /// 生成Insert语句
    /// </summary>
    /// <param name="type"></param>
    /// <returns></returns>
    public string GenerateInsertSQL(Type type) {
      string insertSQL = string.Empty;
      try {
        _logger.Info(string.Format("生成实体类{0}的Insert SQL语句", type.FullName));
        //调用GetCustomAttributes方法获取与DBTable类有关的属性列表，该方法返回一个对象数组
        Object[] tableAttributes = type.GetCustomAttributes(typeof(DBTable), false);
        if (tableAttributes.GetLength(0) != 0) {
          DBTable dbTable = (DBTable)tableAttributes[0];//获取属性类的第一个成员
          string tableName = dbTable.TableName;
          if (!string.IsNullOrWhiteSpace(tableName)) {
            insertSQL = string.Format("INSERT INTO {0}(", tableName);
            string values = string.Format(" VALUES(@");
            PropertyInfo[] propertys = type.GetProperties();
            int fieldCount = propertys.Length;
            for (int i = 0; i < fieldCount; i++) {
              PropertyInfo info = propertys[i];
              Attribute[] dbColumnAttributes = Attribute.GetCustomAttributes(info);
              foreach (Attribute dbColumnAttr in dbColumnAttributes) {
                if (dbColumnAttr.GetType() == typeof(DBColumn)) {
                  string fieldName = ((DBColumn)dbColumnAttr).ColumnName;
                  insertSQL += (i < fieldCount - 1) ? fieldName + "," : fieldName + ")";
                  values += (i < fieldCount - 1) ? info.Name + ",@" : info.Name + ");";
                }
              }
            }
            insertSQL += values;
          }
        }
      } catch (Exception ex) {
        _logger.Error(ex);
        insertSQL = string.Empty;
      }
      _logger.Info(string.Format("实体类{0}的Insert SQL语句    {1}", type.FullName, insertSQL));
      return insertSQL;
    }


    /// <summary>
    /// 生成Insert语句对应的参数
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="t">实体对象</param>
    /// <returns></returns>
    public DbParameter[] ConstructEntityParameters<T>(T t) {
      List<DbParameter> parametersList = new List<DbParameter>();
      Type type = typeof(T);
      try {
        _logger.Info(string.Format("生成类{0}的对象对应的Insert SQL语句参数", type.FullName));
        PropertyInfo[] propertys = type.GetProperties();
        foreach (PropertyInfo proper in propertys) {
          Attribute[] dbColumnAttributes = Attribute.GetCustomAttributes(proper);
          foreach (Attribute dbColumnAttr in dbColumnAttributes) {
            if (dbColumnAttr.GetType() == typeof(DBColumn)) {
              parametersList.Add(new SqlParameter("@" + proper.Name, proper.GetValue(t, null)));
              break;
            }
          }
        }
        
      } catch (Exception ex) {
        _logger.Error(ex);
        parametersList = new List<DbParameter>();
        return parametersList.ToArray();
      }
      _logger.Info(string.Format("生成类{0}的对象对应的Insert SQL语句参数成功。", type.FullName));
      return parametersList.ToArray();
    }


    /// <summary>
    /// 生成Update语句
    /// </summary>
    /// <param name="type"></param>
    /// <returns></returns>
    public string GenerateUpdateSQL(Type type) {
      string updateSQL = string.Empty;
      try {
        _logger.Info(string.Format("生成实体类{0}的Update SQL语句", type.FullName));
        //调用GetCustomAttributes方法获取与DBTable类有关的属性列表，该方法返回一个对象数组
        Object[] tableAttributes = type.GetCustomAttributes(typeof(DBTable), false);
        if (tableAttributes.GetLength(0) != 0) {
          DBTable dbTable = (DBTable)tableAttributes[0];//获取属性类的第一个成员
          string tableName = dbTable.TableName;
          if (!string.IsNullOrWhiteSpace(tableName)) {
            updateSQL = string.Format("UPDATE {0} SET ", tableName);
            string where = string.Empty;
            PropertyInfo[] propertys = type.GetProperties();
            int fieldCount = propertys.Length;
            for (int i = 0; i < fieldCount; i++) {
              PropertyInfo info = propertys[i];
              Attribute[] dbColumnAttributes = Attribute.GetCustomAttributes(info);
              foreach (Attribute dbColumnAttr in dbColumnAttributes) {
                if (dbColumnAttr.GetType() == typeof(DBColumn)) {
                  string fieldName = ((DBColumn)dbColumnAttr).ColumnName;
                  if (((DBColumn)dbColumnAttr).Primariy == true && string.IsNullOrWhiteSpace(where)) {
                    where = string.Format(" WHERE {0}=@{1}; ", fieldName, info.Name);// "  "
                  } else {
                    updateSQL += (i < fieldCount - 1) ? string.Format("{0}=@{1},", fieldName, info.Name) : string.Format("{0}=@{1} ", fieldName, info.Name);
                  }
                }
              }
            }
            updateSQL += where;
          }
        }
      } catch (Exception ex) {
        _logger.Error(ex);
        updateSQL = string.Empty;
      }
      _logger.Info(string.Format("实体类{0}的Update SQL语句    {1}", type.FullName, updateSQL));
      return updateSQL;
    }


    /// <summary>
    /// 生成Update语句对应的参数
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="t">实体对象</param>
    /// <returns></returns>
    public DbParameter[] ConstructUpdateSQLParameters<T>(T t) {
      List<DbParameter> parametersList = new List<DbParameter>();
      Type type = typeof(T);
      try {
        _logger.Info(string.Format("生成类{0}的对象对应的Update SQL语句参数", type.FullName));
        PropertyInfo[] propertys = type.GetProperties();
        foreach (PropertyInfo proper in propertys) {
          Attribute[] dbColumnAttributes = Attribute.GetCustomAttributes(proper);
          foreach (Attribute dbColumnAttr in dbColumnAttributes) {
            if (dbColumnAttr.GetType() == typeof(DBColumn) && ((DBColumn)dbColumnAttr).Primariy == true) {
              parametersList.Add(new SqlParameter("@" + proper.Name, proper.GetValue(t, null)));
              break;
            }
          }
        }
      } catch (Exception ex) {
        _logger.Error(ex);
        parametersList = new List<DbParameter>();
        return parametersList.ToArray();
      }
      _logger.Info(string.Format("生成类{0}的对象对应的Update SQL语句参数成功。", type.FullName));
      return parametersList.ToArray();
    }


    /// <summary>
    /// 生成Delete语句
    /// </summary>
    /// <param name="type"></param>
    /// <returns></returns>
    public string GenerateDeleteSQL(Type type) {
      string deleteSQL = string.Empty;
      try {
        _logger.Info(string.Format("生成实体类{0}的Delete SQL语句", type.FullName));
        //调用GetCustomAttributes方法获取与DBTable类有关的属性列表，该方法返回一个对象数组
        Object[] tableAttributes = type.GetCustomAttributes(typeof(DBTable), false);
        if (tableAttributes.GetLength(0) != 0) {
          DBTable dbTable = (DBTable)tableAttributes[0];//获取属性类的第一个成员
          string tableName = dbTable.TableName;
          if (!string.IsNullOrWhiteSpace(tableName)) {
            deleteSQL = string.Format("DELETE FROM {0} ", tableName);
            string where = string.Empty;
            PropertyInfo[] propertys = type.GetProperties();
            int fieldCount = propertys.Length;
            for (int i = 0; i < fieldCount; i++) {
              PropertyInfo info = propertys[i];
              Attribute[] dbColumnAttributes = Attribute.GetCustomAttributes(info);
              foreach (Attribute dbColumnAttr in dbColumnAttributes) {
                if (dbColumnAttr.GetType() == typeof(DBColumn)) {
                  string fieldName = ((DBColumn)dbColumnAttr).ColumnName;
                  if (((DBColumn)dbColumnAttr).Primariy == true && string.IsNullOrWhiteSpace(where)) {
                    where = string.Format(" WHERE {0}=@{1}; ", fieldName, info.Name);// "  "
                  }
                }
              }
            }
            deleteSQL += where;
          }
        }
      } catch (Exception ex) {
        _logger.Error(ex);
        deleteSQL = string.Empty;
      }
      _logger.Info(string.Format("实体类{0}的Delete SQL语句    {1}", type.FullName, deleteSQL));
      return deleteSQL;
    }

    /// <summary>
    /// 生成根据主键查询一条记录的语句
    /// </summary>
    /// <param name="type"></param>
    /// <returns></returns>
    public string GenerateSelectSQLByPrimaryKey(Type type) {
      string selectOnebyPrimaryKeySQL = string.Empty;
      try {
        _logger.Info(string.Format("生成根据主键查询一条记录的SELECT SQL语句", type.FullName));
        //调用GetCustomAttributes方法获取与DBTable类有关的属性列表，该方法返回一个对象数组
        Object[] tableAttributes = type.GetCustomAttributes(typeof(DBTable), false);
        if (tableAttributes.GetLength(0) != 0) {
          DBTable dbTable = (DBTable)tableAttributes[0];//获取属性类的第一个成员
          string tableName = dbTable.TableName;
          if (!string.IsNullOrWhiteSpace(tableName)) {
            selectOnebyPrimaryKeySQL = string.Format("SELECT");
            string where = string.Empty;
            string fields = string.Empty;
            PropertyInfo[] propertys = type.GetProperties();
            int fieldCount = propertys.Length;
            for (int i = 0; i < fieldCount; i++) {
              PropertyInfo info = propertys[i];
              Attribute[] dbColumnAttributes = Attribute.GetCustomAttributes(info);
              foreach (Attribute dbColumnAttr in dbColumnAttributes) {
                if (dbColumnAttr.GetType() == typeof(DBColumn)) {
                  string fieldName = ((DBColumn)dbColumnAttr).ColumnName;
                  if (((DBColumn)dbColumnAttr).Primariy == true && string.IsNullOrWhiteSpace(where)) {
                    where = string.Format(" WHERE {0}=@{1}; ", fieldName, info.Name);// "  "
                  }
                  fields += (i < fieldCount - 1) ? string.Format("{0},", fieldName) : string.Format("{0}", fieldName);
                }
              }
            }
            selectOnebyPrimaryKeySQL = string.Format("SELECT {0} FROM {1} {2}", fields, tableName, where);
          }
        }
      } catch (Exception ex) {
        _logger.Error(ex);
        selectOnebyPrimaryKeySQL = string.Empty;
      }
      _logger.Info(string.Format("根据主键查询一条记录的SELECT SQL语句    {1}", type.FullName, selectOnebyPrimaryKeySQL));
      return selectOnebyPrimaryKeySQL;
    }

    /// <summary>
    /// 生成主键参数
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="t">实体对象</param>
    /// <returns></returns>
    public DbParameter[] ConstructPrimaryKeyParameter<T>(T t) {
      List<DbParameter> parametersList = new List<DbParameter>();
      Type type = typeof(T);
      try {
        _logger.Info(string.Format("生成类{0}的对象对应的主键参数成功", type.FullName));
        PropertyInfo[] propertys = type.GetProperties();
        foreach (PropertyInfo proper in propertys) {
          Attribute[] dbColumnAttributes = Attribute.GetCustomAttributes(proper);
          foreach (Attribute dbColumnAttr in dbColumnAttributes) {
            if (dbColumnAttr.GetType() == typeof(DBColumn) && ((DBColumn)dbColumnAttr).Primariy == true) {
              parametersList.Add(new SqlParameter("@" + proper.Name, proper.GetValue(t, null)));
              break;
            }
          }
        }
      } catch (Exception ex) {
        _logger.Error(ex);
        parametersList = new List<DbParameter>();
        return parametersList.ToArray();
      }
      _logger.Info(string.Format("生成类{0}的对象对应的主键参数成功。", type.FullName));
      return parametersList.ToArray();
    }
    

    public List<Model.TableInfo> GetAllUserTables() {


      return null;
    }

    public void Dispose() {
      if(connection != null && connection.State == ConnectionState.Open) {
        connection.Close();
      }
    }



    #region 批量导入DataTable

    //public void BulkToDB(string tableName, DataTable dt)
    //{
    //    SQLiteConnection sqlConn = new SQLiteConnection(
    //        ConfigurationManager.ConnectionStrings["connStr"].ConnectionString);
    //    sqlite
    //    SqlBulkCopy bulkCopy = new SqlBulkCopy(sqlConn);
    //    bulkCopy.DestinationTableName = tableName;
    //    bulkCopy.BatchSize = dt.Rows.Count;

    //    try
    //    {
    //        sqlConn.Open();
    //        if (dt != null && dt.Rows.Count != 0)
    //            bulkCopy.WriteToServer(dt);
    //    }
    //    catch (Exception ex)
    //    {
    //        throw ex;
    //    }
    //    finally
    //    {
    //        sqlConn.Close();
    //        if (bulkCopy != null)
    //            bulkCopy.Close();
    //    }
    //}

    #endregion 批量导入DataTable
  }
}
